Online Bookstore

This Project is a mimic of an online bookstore. Users use Browser to cruise the online
bookstore, search and buy books.

Platform: Windows95/98, NT4.0
Software Requirement
    Microsoft Personal Web Server,  NT Server.
    Access Database.
    IE5.0/ Netscape 4.5 or higher, it looks better in IE5.0.

Online Bookstore Application Setup

To set up My Online Bookstore application, follow these steps:

    1. Install Microsoft Personal Web Server on your computer.
    2. Copy the whole folder shop to your hard drive.
    3. Create an ASP Application in a virtual directory on your PWS.

    Start Personal Web Server Manager from Start | Program, Press Start button, the
        name of  your computer is available in the Publishing frame. That name is your servername.
    Click on Advanced, then click Add, choose the shop directory
    In the Alias box, enter shopping
    Click OK

    4. Use the ODBC Data Source Administrator to create a System DSN named  bookstoreDSN.
        This DSN should point to the Microsoft Access database bookstore.mdb located in the shop
        folder.

        Click Start | Control Panel, Click ODBC Data Source Within the ODBC Data Source
            Administrator, choose the tab labeled System DSN.
       Click Add, select the Access Driver, and click Finish.
       Enter bookstoreDSN in the Data Source Name box, and a description for the connection
            (for example: Online Bookstore), click the button labeled Select to choose bookstore.mdb
            which is in the shop folder, click OK to finish.

    5. My Online bookstore application is now ready for visitors! They can browse to
         http://servername/shopping
 

Database: MS Access
    I use Access database, my database is named bookstore, it has 4 tables.

    Books
        It is used to store the information about the book, such as title, author, ISBN etc. ISBN
        is the Primary Key.

    Customers
        It is used to store the customer information such as name, email etc, Email is the Primary Key.

    Orders
        It is used to store the order information such as Order Date, Payment Method etc, each order
        has a Primary Key OrderID.

    OrderDetails
        It is used to store the detail for each order, such as Price for each book, quantity. OrderDetailID
        is the Primary Key, OrderId and CustomerEmail are Foreign Keys.
 

The source code is in 9 files.

Header.inc
    It is included near the beginning of each page, somewhere near the <html> tag. Before the HTML
Include tag is implemented. Asp code in each page sets the values of two variables that will be used
by header.inc. sPageHead is used to set the page’s title inside the <head> tag; sPageCaption specifies
the page’s caption inside a blue bar that resembles a newspaper dateline.

<%'--------------------------------------------------------------------
  'Online Bookstore Application
  'header.inc
  '--------------------------------------------------------------------
%>
<head>
<title><% = sPageHead %></title>
</head>

<body>
<table border="0" width="100%">
  <tr>
    <td width="70%"><a href="default.asp">
    <img src="images/shu.gif"
      alt="Welcome to Our Tiny BookStore" border="0"></a></td>
    <td valign="top">
      <table bgcolor="#dc143c" border="0" width="100%">
        <tr>
          <td bgcolor="#87cefa" align="center">
          <font face="Verdana,Arial" size=-1>
          <a href="default.asp">Online Bookstore Home</a>
          </font></td>
        </tr>
        <tr>
          <td bgcolor="#87cefa" align="center">
          <font face="Verdana,Arial" size=-1>
          <a href="shopcart.asp">Shopping Cart</a>
          </font></td>
        </tr>
      </table>
    </td>
  </tr>
</table>
<table border="0" width="100%">
  <tr>
    <td bgcolor="#0000FF" align="center">
    <font face="Verdana,Arial" color="#ffff00">
    <b><% = sPageCaption %></font></b></td>
  </tr>
</table>
 

Footer.inc
    It is similar to header.inc, footer.inc is designed to give the bottom of each page in the application a
    consistent look.

<%'--------------------------------------------------------------------
  'Online Bookstore Application
  'footer.inc
  '--------------------------------------------------------------------
%>
<br><table border="0" width="100%">
  <tr align="center">
    <td bgcolor="#33ccff">
      <font face="Verdana, Arial" color="#ffff33" size="-1">
      <a href="help.asp">Help</a></font></td>
    <td bgcolor="#33ccff">
      <font face="Verdana, Arial" color="#ffff33" size="-1">
      <a href="shopcart.asp">Shopping Cart</a></font></td>
    <td bgcolor="#33ccff">
      <font face="Verdana, Arial" color="#ffff33" size="-1">
      <a href="custsvc.asp">Customer Service</a></font></td>
    <td bgcolor="#33ccff">
      <font face="Verdana, Arial" color="#ffff33" size="-1">
      <a href="feedback.asp">Feedback</a></font></td>
  </tr>
</table>
<br>
<hr align="CENTER" size="2" color="#0000FF">
<div align="center"><font face="Arial" color="#808080" size=-2>
</font>
</div><hr align="CENTER" size="2" color="#0000FF">
 

Global.asp
    It sets up session variables to be used throughout the application.

<SCRIPT LANGUAGE=VBScript RUNAT=Server>
Sub Session_OnStart
  dim sItemNums(0), nItemQtys(0)
  sItemNums(0) = ""
  nItemQtys(0) = 0

  session("CartItemNumArray") = sItemNums
  session("CartItemQtyArray") = nItemQtys
  session("DBLogin") = "DSN=bookstoreDSN"
  session("shipbasecharge") = 4.50
  session("shipitemcharge") = 1.25

End Sub
</SCRIPT>
 

Adovbs.inc
    It is provided by Microsoft, allows VBScript application easy access to predefined ADO constants.

<%
'--------------------------------------------------------------------
' Microsoft ADO
'
' (c) 1996 Microsoft Corporation.  All Rights Reserved.
'
'ADO constants include file for VBScript
'--------------------------------------------------------------------

'---- CursorTypeEnum Values ----
Const adOpenForwardOnly = 0
Const adOpenKeyset = 1
Const adOpenDynamic = 2
Const adOpenStatic = 3

'---- CursorOptionEnum Values ----
Const adHoldRecords = &H00000100
Const adMovePrevious = &H00000200
Const adAddNew = &H01000400
Const adDelete = &H01000800
Const adUpdate = &H01008000
Const adBookmark = &H00002000
Const adApproxPosition = &H00004000
Const adUpdateBatch = &H00010000
Const adResync = &H00020000
Const adNotify = &H00040000

'---- LockTypeEnum Values ----
Const adLockReadOnly = 1
Const adLockPessimistic = 2
Const adLockOptimistic = 3
Const adLockBatchOptimistic = 4

'---- ExecuteOptionEnum Values ----
Const adRunAsync = &H00000010

'---- ObjectStateEnum Values ----
Const adStateClosed = &H00000000
Const adStateOpen = &H00000001
Const adStateConnecting = &H00000002
Const adStateExecuting = &H00000004

'---- CursorLocationEnum Values ----
Const adUseServer = 2
Const adUseClient = 3

'---- DataTypeEnum Values ----
Const adEmpty = 0
Const adTinyInt = 16
Const adSmallInt = 2
Const adInteger = 3
Const adBigInt = 20
Const adUnsignedTinyInt = 17
Const adUnsignedSmallInt = 18
Const adUnsignedInt = 19
Const adUnsignedBigInt = 21
Const adSingle = 4
Const adDouble = 5
Const adCurrency = 6
Const adDecimal = 14
Const adNumeric = 131
Const adBoolean = 11
Const adError = 10
Const adUserDefined = 132
Const adVariant = 12
Const adIDispatch = 9
Const adIUnknown = 13
Const adGUID = 72
Const adDate = 7
Const adDBDate = 133
Const adDBTime = 134
Const adDBTimeStamp = 135
Const adBSTR = 8
Const adChar = 129
Const adVarChar = 200
Const adLongVarChar = 201
Const adWChar = 130
Const adVarWChar = 202
Const adLongVarWChar = 203
Const adBinary = 128
Const adVarBinary = 204
Const adLongVarBinary = 205

'---- FieldAttributeEnum Values ----
Const adFldMayDefer = &H00000002
Const adFldUpdatable = &H00000004
Const adFldUnknownUpdatable = &H00000008
Const adFldFixed = &H00000010
Const adFldIsNullable = &H00000020
Const adFldMayBeNull = &H00000040
Const adFldLong = &H00000080
Const adFldRowID = &H00000100
Const adFldRowVersion = &H00000200
Const adFldCacheDeferred = &H00001000

'---- EditModeEnum Values ----
Const adEditNone = &H0000
Const adEditInProgress = &H0001
Const adEditAdd = &H0002
Const adEditDelete = &H0004

'---- RecordStatusEnum Values ----
Const adRecOK = &H0000000
Const adRecNew = &H0000001
Const adRecModified = &H0000002
Const adRecDeleted = &H0000004
Const adRecUnmodified = &H0000008
Const adRecInvalid = &H0000010
Const adRecMultipleChanges = &H0000040
Const adRecPendingChanges = &H0000080
Const adRecCanceled = &H0000100
Const adRecCantRelease = &H0000400
Const adRecConcurrencyViolation = &H0000800
Const adRecIntegrityViolation = &H0001000
Const adRecMaxChangesExceeded = &H0002000
Const adRecObjectOpen = &H0004000
Const adRecOutOfMemory = &H0008000
Const adRecPermissionDenied = &H0010000
Const adRecSchemaViolation = &H0020000
Const adRecDBDeleted = &H0040000

'---- GetRowsOptionEnum Values ----
Const adGetRowsRest = -1

'---- PositionEnum Values ----
Const adPosUnknown = -1
Const adPosBOF = -2
Const adPosEOF = -3

'---- enum Values ----
Const adBookmarkCurrent = 0
Const adBookmarkFirst = 1
Const adBookmarkLast = 2

'---- MarshalOptionsEnum Values ----
Const adMarshalAll = 0
Const adMarshalModifiedOnly = 1

'---- AffectEnum Values ----
Const adAffectCurrent = 1
Const adAffectGroup = 2
Const adAffectAll = 3

'---- FilterGroupEnum Values ----
Const adFilterNone = 0
Const adFilterPendingRecords = 1
Const adFilterAffectedRecords = 2
Const adFilterFetchedRecords = 3
Const adFilterPredicate = 4

'---- SearchDirection Values ----
Const adSearchForward = 1
Const adSearchBackward = -1

'---- ConnectPromptEnum Values ----
Const adPromptAlways = 1
Const adPromptComplete = 2
Const adPromptCompleteRequired = 3
Const adPromptNever = 4

'---- ConnectModeEnum Values ----
Const adModeUnknown = 0
Const adModeRead = 1
Const adModeWrite = 2
Const adModeReadWrite = 3
Const adModeShareDenyRead = 4
Const adModeShareDenyWrite = 8
Const adModeShareExclusive = &Hc
Const adModeShareDenyNone = &H10

'---- IsolationLevelEnum Values ----
Const adXactUnspecified = &Hffffffff
Const adXactChaos = &H00000010
Const adXactReadUncommitted = &H00000100
Const adXactBrowse = &H00000100
Const adXactCursorStability = &H00001000
Const adXactReadCommitted = &H00001000
Const adXactRepeatableRead = &H00010000
Const adXactSerializable = &H00100000
Const adXactIsolated = &H00100000

'---- XactAttributeEnum Values ----
Const adXactCommitRetaining = &H00020000
Const adXactAbortRetaining = &H00040000

'---- PropertyAttributesEnum Values ----
Const adPropNotSupported = &H0000
Const adPropRequired = &H0001
Const adPropOptional = &H0002
Const adPropRead = &H0200
Const adPropWrite = &H0400

'---- ErrorValueEnum Values ----
Const adErrInvalidArgument = &Hbb9
Const adErrNoCurrentRecord = &Hbcd
Const adErrIllegalOperation = &Hc93
Const adErrInTransaction = &Hcae
Const adErrFeatureNotAvailable = &Hcb3
Const adErrItemNotFound = &Hcc1
Const adErrObjectInCollection = &Hd27
Const adErrObjectNotSet = &Hd5c
Const adErrDataConversion = &Hd5d
Const adErrObjectClosed = &He78
Const adErrObjectOpen = &He79
Const adErrProviderNotFound = &He7a
Const adErrBoundToCommand = &He7b
Const adErrInvalidParamInfo = &He7c
Const adErrInvalidConnection = &He7d
Const adErrStillExecuting = &He7f
Const adErrStillConnecting = &He81

'---- ParameterAttributesEnum Values ----
Const adParamSigned = &H0010
Const adParamNullable = &H0040
Const adParamLong = &H0080

'---- ParameterDirectionEnum Values ----
Const adParamUnknown = &H0000
Const adParamInput = &H0001
Const adParamOutput = &H0002
Const adParamInputOutput = &H0003
Const adParamReturnValue = &H0004

'---- CommandTypeEnum Values ----
Const adCmdUnknown = &H0008
Const adCmdText = &H0001
Const adCmdTable = &H0002
Const adCmdStoredProc = &H0004

'---- SchemaEnum Values ----
Const adSchemaProviderSpecific = -1
Const adSchemaAsserts = 0
Const adSchemaCatalogs = 1
Const adSchemaCharacterSets = 2
Const adSchemaCollations = 3
Const adSchemaColumns = 4
Const adSchemaCheckConstraints = 5
Const adSchemaConstraintColumnUsage = 6
Const adSchemaConstraintTableUsage = 7
Const adSchemaKeyColumnUsage = 8
Const adSchemaReferentialContraints = 9
Const adSchemaTableConstraints = 10
Const adSchemaColumnsDomainUsage = 11
Const adSchemaIndexes = 12
Const adSchemaColumnPrivileges = 13
Const adSchemaTablePrivileges = 14
Const adSchemaUsagePrivileges = 15
Const adSchemaProcedures = 16
Const adSchemaSchemata = 17
Const adSchemaSQLLanguages = 18
Const adSchemaStatistics = 19
Const adSchemaTables = 20
Const adSchemaTranslations = 21
Const adSchemaProviderTypes = 22
Const adSchemaViews = 23
Const adSchemaViewColumnUsage = 24
Const adSchemaViewTableUsage = 25
Const adSchemaProcedureParameters = 26
Const adSchemaForeignKeys = 27
Const adSchemaPrimaryKeys = 28
Const adSchemaProcedureColumns = 29
%>
 

Procs.inc
    It contains a sub procedure and a function that will be used by multiple pages.

<%
'------------------------------------------------------
'Online BookStore Application
'proc.inc
'------------------------------------------------------

Sub WriteProductRow
  'Write a table row for the current record of rsProducts
  response.write "  <tr>" & vbcrlf

  'First cell for picture
  sTemp = trim("" & rsproducts("picture"))
  if sTemp = "" then
    sTemp = "Picture Not Available"
  else
    sTemp = "<img src='images\products\" & sTemp & "' border=0 alt=''>"
  end if
  response.write "    <td align='center'>"
  response.write "<font face='Verdana, Arial' color='#008000' size='-1'>"
  response.write sTemp & "</font></td>" & vbcrlf

  'Second cell for Title, Isbn, Publisher
  response.write "    <td valign='top'>"
  response.write "<font face='Verdana, Aria' color='#0000ff' size='2'>"
  response.write "<u>" & rsProducts("Title")
  response.write "</u></font><br>"

  response.write "<font face='Verdana, Arial' color='#008000' size='-2'>"
  response.write "<b><I>ISBN: </i>" & rsProducts("ISBN") & "</b><br>"

  response.write "<font face='Verdana, Arial' color='#0000ff' size='-1'>"
  response.write "<b><I>Author: </i>" & rsProducts("Author") & "</b><br>"

  response.write "<font face='Verdana, Arial' color='#008000' size='-1'>"
  response.write "<i>Publisher: </i> " & rsProducts("Publisher") & "<br>"

  response.write "<font face='Verdana, Arial' color='#0008000' size='-2'>"
  response.write "<b><I>Description: </i>" & rsProducts("Description") & "</b>"

  response.write "</font></td>" & vbcrlf

  stemp = "Price: " & formatcurrency(rsProducts("Price"))

  response.write "    <td align='center' valign='middle' nowrap>"
  response.write "<font face='Verdana, Arial' color='#0000ff' size='-1'>"
  response.write sTemp & "<br><br>"
  response.write "<a href='shopcart.asp?mode=add&isbnNO="
  response.write rsproducts("ISBN") & "'></font>"
  response.write "<img src='images/addtocart.jpg' border='0'></a></td>"
  response.write vbcrlf

  response.write "  </tr>"  & vbcrlf

End Sub

Function RemoveQuotes(s)
  dim i, s2
  s = trim(s)

  if len(s) = 0 then
    RemoveQuotes = ""
    exit function
  end if

  s2 = ""
  for i = 1 to len(s)
    if mid(s,i,1) = "'" then
      s2 = s2 & "''"
    else
      s2 = s2 & mid(s, i, 1)
    end if
  next
  RemoveQuotes = s2
End Function
%>
 

Default.asp
    It allows the user to input the search string (book title or ISBN number), and displays today’s feature
    presentation.

<%'--------------------------------------------------------------------
  'Online Bookstore Application
  'default.asp
  '--------------------------------------------------------------------
%>
<!--#INCLUDE FILE="adovbs.inc"-->
<!--#INCLUDE FILE="procs.inc"-->
<%
    sPageHead = "CSC8560 Computer Network Project Online Bookstore Application"
    sPageCaption = formatdatetime(now,vblongdate)
    session("redirectto") = "default.asp"
    session("salecomplete") = false
%>
<html>
<!--#INCLUDE FILE="header.inc"-->
<form action="search.asp" method="POST" id=form1 name=form1>
<table border="0" width="100%">
  <tr>
    <td width="50%">
      <table border="0" width="100%" bgcolor="#c0c0c0" cellspacing="0">
        <tr>
          <td align="center" bgcolor=#66ccff colspan=3>
          <font face="Verdana,Arial" size=-1>
          <strong>BOOK SEARCH</strong></font></td>
        </tr>
        <tr>
           <td> <i>ISBN/Title</i></td>
           <td><input type="Text" name="requestString" size="20"
                 maxlength="100"></td>
           <td><input type="submit" value="Search" name=search>
            </td>
         <tr>
            <td> <input type= radio value="byTitle" name=searchMethod>By Title</td>
   <td> <input type= radio value="byISBN" name=searchMethod>By ISBN</td>
   </tr>
   <tr>
     <td colspan=3><font face="Verdana,Arial" color="#000000" size="-2" >
                  Enter ISBN Number or Title of the book, then click Search.
               </font>
           </td>
         </tr>
          <tr>
   <td align="center" colspan=3 bgcolor=#66ccff>
   <font face="Verdana,Arial" size=-1>
   <strong>BOOK BROWSE</strong></font></td>
    </tr>
    <tr>
   <td><input type="submit" value="Shop List" name=showList></td>
    </tr>
    <tr>
      <td colspan="3"><font face="Verdana,Arial" color="#000000" size="-2" >
     Or show the whole list of our bookstore</font></td>
    </tr>
       </table>
    </form>
    <td valign="top">
      <font face="Verdana,Arial" color="#008000" size="-1">
      Welcome to Our Tiny Bookstore! feel free to look around
      and select books you're interested in.
      <br>
      <form action="shopcart.asp" method="POST">
      Begin shopping by click "Empty Shopping Cart"</font><br><br>
      <input type="Submit" name="cmdSubmit" value="Empty Shopping Cart">
      </form>
    </td>
  </tr>

</table>
 

<%
  set dbMain = server.createobject("ADODB.Connection")
  dbMain.open "DSN=bookstoreDSN"
  Set rsProducts = Server.CreateObject("ADODB.Recordset")
  sSQL = "SELECT * FROM books"
  rsProducts.open sSQL, dbMain, adopenstatic, adlockpessimistic, adcmdtext
%>
<% if not rsproducts.eof then %>
<table border="0" width="100%">
  <tr>
  <td bgcolor="#0000FF"><font face="Verdana,Arial" color="#ffff00">
    <p align="center"><b>Today's Featured Products</b></p></font></td>
  </tr>
</table>
<br>
<table width="75%" border="1" align="center">
<%
  rsProducts.movefirst
  do while not rsproducts.eof
    WriteProductRow
    rsProducts.movenext
  loop
%>
</table>
<%end if%>
<!--#INCLUDE FILE="footer.inc"-->
</body>
</html>
 

Search.asp
    It searches the bookstore database, returns the search result.

<%'--------------------------------------------------------------------
  'Online Bookstore Application
  'search.asp
  '--------------------------------------------------------------------
%>
<!--#INCLUDE FILE="adovbs.inc"-->
<!--#INCLUDE FILE= "procs.inc"-->
 

<%
  set dbMain = server.createobject("ADODB.Connection")
  dbMain.open "DSN=bookstoreDSN"
  Set rsProducts = Server.CreateObject("ADODB.Recordset")

  requestString = RemoveQuotes(request.Form("requestString"))
  requestAction = request.Form ("showList")
  searchMethod = request.Form ("searchMethod")

  If requestString = "" OR requestAction = "Shop List" then
 sSQL = "SELECT * FROM bookS ORDER By Title"
 sPageHead = "CSC8560 Project Online Bookstore Book Browse"
    sPageCaption = "Book Browse"
  Else
    sPageHead = "CSC8560 Project Online Bookstore Search Results"
 sPageCaption = "Book Search Results"
    If (searchMethod = "byTitle")Then
      sSQL = "SELECT * FROM books WHERE Title LIKE '%" & requestString & "'"
    Else
      sSQL = "SELECT * FROM books WHERE ISBN = '" & requestString & "'"
    End If
  End If

  rsProducts.open sSQL, dbMain, adopenstatic, adlockpessimistic, adcmdtext
%>
  <html>
  <!--#INCLUDE FILE="header.inc"-->
  <br>
<%
  If (rsProducts.BOF) AND (rsProducts.EOF) then
  %>

    <font face="Verdana,Arial" color="#008000" size="4">
  <%
 Response.Write("Sorry, No record was Found")
    Response.Write vbcrlf%>
    <br></font>
  <%
  ELSE
%>

  <table width="75%" border="1" align="center">
<%
  rsProducts.movefirst
  do while not rsproducts.eof
    WriteProductRow
    rsProducts.movenext
  loop
%>
 </table>
<%end if%>

<!--#INCLUDE FILE="footer.inc"-->
</body>
</html>
 

Shopcart.asp
    It is the online bookstore workhorse page. It is designed to run in one of several modes:
        Continue Shopping, Recalculate Order,  Empty Shopping Cart,  and Checkout.
    If user chooses Continue Shopping button, he will return to the homepage of the bookstore.
    If user changes the quantity of the book, he can click Recalculate Order button to get the
        Most recently account balance of Shopping Cart.
    If user chooses Empty Shopping Cart, the Shopping Cart is emptied.
    If user chooses Proceed to Checkout, he is required to enter the customer information,
        then he  can submit his order. The customer information is checked and stored in the database.
    So next time when he visits the bookstore again, he already has an account here, he does not need
        to enter the whole information.

<%'--------------------------------------------------------------------
  'Online Bookstore Application
  'shopcart.asp
  '--------------------------------------------------------------------
%>
<!--#INCLUDE FILE="adovbs.inc"-->
<%
  sCartItemNums = session("cartitemnumarray")
  nCartItemQtys = session("cartitemqtyarray")
  nNumCartItems = ubound(sCartItemNums)

  'Determine the mode of this page's operation. If we got here from a
  '  link that had a "mode" querystring of "add", mode is add:
  sMode = request.querystring("mode")

  'Or, we could have gotten here from a form:
  select case request.form("cmdSubmit")
    case "Proceed to Checkout"
      sMode = "checkout"
    case "Recalculate Order"
      sMode = "recalc"
    case "Continue Shopping"
      sMode = "continue"
    case "Empty Shopping Cart"
      sMode="empty"
  end select

  if sMode = "add" then
    nThisItemIndex = 0
    sItemNo = ucase(request.querystring("isbnNO"))
    if nNumCartItems > 0 then
      for i = 1 to nNumCartItems
        if ucase(scartitemnums(i)) = sItemNo then
           nThisItemIndex = i
          exit for
        end if
      next
    end if
    if nThisItemIndex = 0 then
      nThisItemIndex = nNumCartItems + 1
      redim Preserve sCartItemNums(nThisItemIndex)
      redim Preserve nCartItemQtys(nThisItemIndex)
      sCartItemNums(nThisItemIndex) = sItemNo
      nCartItemQtys(nThisItemIndex) = 1
    else
      nCartItemQtys(nThisItemIndex) = nCartItemQtys(nThisItemIndex) + 1
    end if
    session("cartitemnumarray") = sCartItemNums
    session("cartitemqtyarray") = nCartItemQtys
    nNumCartItems = ubound(sCartItemNums)
  end if

  if sMode = "recalc" or sMode = "checkout" or sMode = "continue" then
    for i = 1 to nNumCartItems
      nThisQty = int(request.form("txtItemQty" & i))
      nCartItemQtys(i) = nThisQty
    next
    session("cartitemnumarray") = sCartItemNums
    session("cartitemqtyarray") = nCartItemQtys
  end if

  'Move to another page based on mode.
  '  If mode is "add" or "recalc", we stay here.
  '  If mode is "continue", we move back to the main page so the user
  '    can shop more.
  '  If mode is "checkout", we stay here but change the mode to checkout
  '  If mode is empty shopping card, we empty shoppingcart and stay here
  if sMode = "continue" then
      response.redirect("default.asp")
  end if
  if sMode = "empty" then
     redim sItemNums(0)
  redim nItemQtys(0)
  sItemNums(0) = ""
  nItemQtys(0) = 0
  nNumCartItems = 0
  session("CartItemNumArray") = sItemNums
  session("CartItemQtyArray") = nItemQtys
  session("salecomplete") = false
  end if

  set dbMain = server.createobject("ADODB.Connection")
  dbMain.open "DSN=bookstoreDSN"

  if sMode = "checkout" then
    sPageHead = "Our Online Bookstore Checkout"
    sPageCaption = "Checkout"
  else
    sPageHead = "Bookstore Shopping Cart"
    sPageCaption = "Shopping Cart"
  end if

%>
<html>

<!--#INCLUDE FILE="header.inc"-->

<br>
<font face="Verdana,Arial" color="#008000" size="-1">
<% if sMode = "checkout" then %>
<form action="submitorder.asp" method="POST">
<% else %>
<form action="shopcart.asp" method="POST">
<% end if %>
<%
  if nNumCartItems = 0 then
    response.write "There are no items in your shopping cart.<br>"
  else
    if sMode = "checkout" then
%>
<center><h2><font color=red>
   This is a course project, please do not enter your real credit card number!!!
</font></h2></center>
<br>
Your order is ready to submit. Please provide the following information
and click the "Submit Order" button, if you have a account in our bookstore,
enter your email_address then click "Submit Order" button .
<br><br>
<table align="center" border="0">
  <tr bgcolor="#c0c0c0">
    <th colspan="2" align="center"><font face="Verdana,Arial" size="-1">
      Customer Information</td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">Name:</td>
    <td><font face="Verdana,Arial" size="-1">
      <input type="Text" name="txtCustomerName" size="30" maxlength="30">
      </td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">Email:</td>
    <td><font face="Verdana,Arial" size="-1">
      <input type="Text" name="txtEmail" size="30" maxlength="30">
      </td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">Address:</td>
    <td><font face="Verdana,Arial" size="-1">
      <input type="Text" name="txtAddress" size="30" maxlength="30"></td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">
      City/State/ZIP:</td>
    <td><font face="Verdana,Arial" size="-1">
      <input type="Text" name="txtCity" size="25" maxlength="30">
      <input type="Text" name="txtState" size="4" maxlength="4">
      <input type="Text" name="txtZIP" size="7" maxlength="7"></td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">
      Daytime Phone:</td>
    <td><font face="Verdana,Arial" size="-1">
      <input type="Text" name="txtPhone" size="15" maxlength="15"></td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">
      Payment Method:</td>
    <td><font face="Verdana,Arial" size="-1">
      <input type="Radio" name="optPaymentType" value="visa">
        Visa&nbsp;
      <input type="Radio" name="optPaymentType" value="mc">
        Mastercard&nbsp;
      <input type="Radio" name="optPaymentType" value="amex">
        American Express
    </td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">
      Account Number:</td>
    <td><font face="Verdana,Arial" size="-1">
      <input type="Text" name="txtAcctNo" size="20" maxlength="20"></td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">
      Expiration (mm/yyyy):</td>
    <td><font face="Verdana,Arial" size="-1">
      <input type="Text" name="txtExpDate" size="10" maxlength="7"></td>
  </tr>
</table>
<%
    else
      response.write "Your shopping cart currently contains these items:"
    end if
%>
<br><br>
<table align="center" border="0">
  <tr bgcolor="#ff0066">
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">
      Quantity</font></td>
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">
      ISBN No.</font></td>
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">
       Book Name</font></td>
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">
      Price</font></td>
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">
      Extension</font></td>
  </tr>
<%
  cSubTotal = 0
  nNumItems = 0
  for i = 1 to nNumCartItems
    Set rsProducts = Server.CreateObject("ADODB.Recordset")
    sSQL = "SELECT * FROM books WHERE ISBN = '" & _
       sCartItemNums(i) & "'"
    rsProducts.open sSQL, dbMain, adopenstatic, _
      adlockpessimistic, adcmdtext
%>
  <tr bgcolor="#99ccff">
<%
  sTemp = "<input type='Text' name='txtItemQty" & i & "' value='" & _
    nCartItemQtys(i) & "' size='3'>"
  nNumItems = nNumItems + nCartItemQtys(i)
%>
    <td align="center">
      <font face="Verdana,Arial" color="#000000" size="-1">
      <% = sTemp %></font></td>
    <td align="center">
      <font face="Verdana,Arial" color="#000000" size="-1">
      <% = rsProducts("ISBN") %></font></td>
    <td><font face="Verdana,Arial" color="#000000" size="-1">
      <% = rsProducts("Title") %></font></td>
<%
    cPrice = rsProducts("Price")

%>
    <td align="center">
      <font face="Verdana,Arial" color="#000000" size="-1">
      <% = formatcurrency(rsProducts("Price")) %></font></td>
<%
  cExtension = nCartItemQtys(i) * cPrice
  cSubTotal = cSubTotal + cExtension
%>
    <td align="right">
      <font face="Verdana,Arial" color="#000000" size="-1">
      <% = formatcurrency(cExtension) %></font></td>
  </tr>
<% next %>
  <tr bgcolor="#c5c5c5">
    <td align="center" colspan="4">
      <font face="Verdana,Arial" size="-1">Subtotal</font></td>
    <td align="right"><font face="Verdana,Arial" size="-1">
      <% = formatcurrency(cSubTotal) %></font></td>
  </tr>
<% cShipping = 4.50 + (1.25 * nNumItems) %>
  <tr bgcolor="#c5c5c5">
    <td align="center" colspan="4">
      <font face="Verdana,Arial" size="-1">Shipping & Handling</font></td>
    <td align="right"><font face="Verdana,Arial" size="-1">
      <% = formatcurrency(cShipping) %></font></td>
  </tr>
<% cTotal = cSubTotal + cShipping %>
  <tr bgcolor="#66ff00">
    <td align="center" colspan = "4">
      <font face="Verdana,Arial" size="-1">Grand Total</font></td>
    <td align="right"><font face="Verdana,Arial" size="-1">
      <% = formatcurrency(cTotal) %></font></td>
  </tr>
</table>
<br><div align="center">
<br>
<% if sMode = "checkout" then %>
<input type="Submit" name="cmdSubmit" value="Submit Order">
<input type="Reset" name="cmdSubmit" value="Cancel">
<% else %>
<input type="Submit" name="cmdSubmit" value="Continue Shopping">
<input type="Submit" name="cmdSubmit" value="Recalculate Order">
<input type="Submit" name="cmdSubmit" value="Empty Shopping Cart">
<br><br>
<center>
  <input type="Submit" name="cmdSubmit" value="Proceed to Checkout">
</center>
<% end if %>
</div></form>
<% end if %>

<!--#INCLUDE FILE="footer.inc"-->
</body>
</html>
 

Submitorder.asp
    It is responsible for adding the order information to the database and provides a summary of  the order
        that the user may print out.

<%'--------------------------------------------------------------------
  'Online Bookstore Application
  'submitorder.asp
  '--------------------------------------------------------------------
%>
<!--#INCLUDE FILE="adovbs.inc"-->
<%
  dim sErrorString
  sErrorString = ""
  dim cItemPrice(99), sItemName(99)
  dim cOrderTotal
  cItemPrice(0) = 0
  sItemName(0) = ""
  cOrderTotal = 0
 

  if session("salecomplete") = true then
    session("salecomplete") = false
  end if

  sCartItemNums = session("cartitemnumarray")
  nCartItemQtys = session("cartitemqtyarray")
  nNumCartItems = ubound(sCartItemNums)

  for i = 1 to nNumCartItems
    nThisQty = int(request.form("txtItemQty" & i))
    nCartItemQtys(i) = nThisQty
  next
  session("cartitemnumarray") = sCartItemNums
  session("cartitemqtyarray") = nCartItemQtys

  Sub CheckErrors(sField, sItemName)
 if trim(request.form(sField)) = "" then
    sErrorString = sErrorString & "The " & sItemName & _
   " field cannot be blank.<br>"
 end if
  End Sub

  if(nNumCartItems = 0) then
   Response.redirect "shopcart.asp"
  end if

  CheckErrors "txtEmail","Email"
  CheckErrors "optPaymentType","Payment Type"
  CheckErrors "txtAcctNo","Account Number"
  CheckErrors "txtExpDate","Expiration Date"

  if sErrorString = "" then
 customerEmail = Request.Form("txtEmail")

 set dbMain = server.createobject("ADODB.Connection")
 dbMain.open "DSN=bookstoreDSN"
 Set rsAccount = Server.CreateObject("ADODB.Recordset")
 sSQL = "SELECT * FROM customers WHERE Email = '" & customerEmail & "'"
 rsAccount.open sSQL, dbMain, adOpenStatic, adlockpessimistic, adcmdtext

 if(rsAccount.BOF OR rsAccount.EOF) then
  CheckErrors "txtCustomerName","Customer Name"
  CheckErrors "txtAddress","Customer Address"
  CheckErrors "txtCity","City"
  CheckErrors "txtState","State"
  CheckErrors "txtZIP","ZIP"
  CheckErrors "txtPhone","Telephone"

  if sErrorString = "" then
   rsAccount.addnew
   rsAccount("Name") = request.form("txtCustomerName")
   rsAccount("Email") = request.form("txtEmail")
   rsAccount("Address") = request.form("txtAddress")
   rsAccount("City") = request.form("txtCity")
   rsAccount("State") = request.form("txtState")
   rsAccount("Zip") = request.form("txtZIP")
   rsAccount("Phone") = request.form("txtPhone")
   rsAccount.update
  end if
   end if
   rsAccount.close
  end if

  if sErrorString = "" then
  Set rsProducts = Server.CreateObject("ADODB.Recordset")

 for i = 1 to nNumCartItems
  sSQL = "SELECT * FROM books WHERE ISBN = '" & _
  sCartItemNums(i) & "'"
  rsProducts.open sSQL, dbMain, adopenstatic, _
  adlockpessimistic, adcmdtext

  cItemPrice(i) = rsProducts("Price")
  sItemName(i) = rsProducts("Title")
  cOrderTotal = cOrderTotal + (nCartItemQtys(i) * cItemPrice(i))
  nNumItems = nNumItems + nCartItemQtys(i)
  rsProducts.close
 next
 cShipping = session("shipbasecharge") + _
  (nNumItems * session("shipitemcharge"))
 cOrderTotal = cOrderTotal + cShipping

 dbMain.BeginTrans
  Set rsOrders = Server.CreateObject("ADODB.Recordset")
  sSQL = "SELECT * FROM orders"
  rsOrders.open sSQL, dbMain, adOpenStatic, adlockpessimistic, adcmdtext

  rsOrders.addnew
   rsOrders("OrderDate") = date()
   rsOrders("customerEmail") = customerEmail
   rsOrders("OrderAmount") = cOrderTotal
   rsOrders("PaymentMethod") = request.form("optPaymentType")
   rsOrders("PaymentAccount") = request.form("txtAcctNo")
   rsOrders("Expdate") = request.form("txtExpDate")
     rsOrders.update
  rsOrders.movelast
  nOrderID = rsOrders("orderID")
  rsOrders.close

  Set rsOrderLines = Server.CreateObject("ADODB.Recordset")
  sSQL = "SELECT * FROM orderDetails"
  rsOrderLines.open sSQL, dbMain, adOpenStatic, _
   adlockpessimistic, adcmdtext

  for i = 1 to nNumCartItems
   rsOrderLines.addnew
   rsOrderLines("OrderID") = nOrderID
   rsOrderLines("ISBN") = sCartItemNums(i)
   rsOrderLines("Quantity") = nCartItemQtys(i)
   rsOrderLines("Price") = cItemPrice(i)
   rsOrderLines.update
  next

 dbMain.CommitTrans
   session("salecomplete") = true
  End if

   sPageHead = "Online Bookstore Order Confirmation"
   sPageCaption = "Order Confirmation"

%>
<html>
<!--#INCLUDE FILE="header.inc"-->
<font face="Verdana,Arial" color="#008000" size="-1"><%
  if sErrorString = "" then
    response.write "Order # " & nOrderID & " has been entered. Use " & _
      " your browser's PRINT function to print a copy of this order." & _
      "<br><br>"
    sSQL = "SELECT * FROM orders WHERE OrderID = " & nOrderID
    rsOrders.open sSQL, dbMain, adOpenStatic, adlockpessimistic, adcmdtext
%>
 

<head>
<title></title>
</head>

<body>

<table align="center" border="0">
  <tr>
    <td valign="top"><table border="0">
      <tr>
        <td align="center" bgcolor="#808080"><font color="#ffffff"><b>Order # <% = nOrderID %> </b></font></td>
      </tr>
      <tr>
        <td align="center" bgcolor="#3300ff"><font color="#ffffff"><b>Order Date <% = date() %> </b></font></td>
      </tr>
    </table>
    </td>
    <td><table align="center" border="0">
      <tr bgcolor="#c0c0c0">
        <th align="center"><font face="Verdana,Arial" size="-1">Customer Information</font></th>
      </tr>
    </table>
    </td>
<%sSql = "SELECT * FROM customers WHERE Email= '" & rsOrders("CustomerEmail") & "'"
          rsAccount.Open sSql, dbMain,adOpenStatic, adlockpessimistic, adcmdtext
        %>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">Name:</font></td>
    <td><font face="Verdana,Arial" size="-1" color="#0000ff"><% = rsAccount("Name") %></font></td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">Address:</font></td>
    <td><font face="Verdana,Arial" size="-1" color="#0000ff"><% = rsAccount("Address") %></font></td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">City/State/ZIP:</font></td>
    <td><font face="Verdana,Arial" size="-1" color="#0000ff"><% = rsAccount("City") & ", " %> <% = rsAccount("State") %> <% = " " & rsAccount("Zip") %></font></td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">Daytime Phone:</font></td>
    <td><font face="Verdana,Arial" size="-1" color="#0000ff"><% = rsAccount("Phone") %></font></td>
  </tr>
  <tr>
    <td align="right"><font face="Verdana,Arial" size="-1">Payment Method:</font></td>
<%
        select case rsOrders("paymentmethod")
          case "visa"
            sTemp = "Visa"
          case "mc"
            sTemp = "MasterCard"
          case "amex"
            sTemp = "American Express"
        end select
%>
    <td><font face="Verdana,Arial" size="-1" color="#0000ff"><% = sTemp %></font></td>
  </tr>
</table>

<p><br>
<br>
</p>

<table align="center" border="0">
  <tr bgcolor="#ff0066">
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">Quantity</font> </th>
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">ISBN No.</font> </th>
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">Book Name</font> </th>
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">Price</font> </th>
    <th><font face="Verdana,Arial" color="#ffff33" size="-1">Extension</font> </th>
  </tr>
<%
  cSubTotal = 0
  nNumItems = 0
  for i = 1 to nNumCartItems
%>
  <tr bgcolor="#99ccff">
    <td align="center"><font face="Verdana,Arial" color="#000000" size="-1"><% = nCartItemQtys(i) %></font></td>
    <td align="center"><font face="Verdana,Arial" color="#000000" size="-1"><% = sCartItemNums(i) %></font></td>
    <td><font face="Verdana,Arial" color="#000000" size="-1"><% = sItemName(i) %></font></td>
    <td align="center"><font face="Verdana,Arial" color="#000000" size="-1"><% = formatcurrency(cItemPrice(i)) %></font></td>
<%
  nNumItems = nNumItems + nCartItemQtys(i)
  cExtension = nCartItemQtys(i) * cItemPrice(i)
  cSubTotal = cSubTotal + cExtension
%>
    <td align="right"><font face="Verdana,Arial" color="#000000" size="-1"><% = formatcurrency(cExtension) %></font></td>
  </tr>
<% next %>
  <tr bgcolor="#c5c5c5">
    <td align="center" colspan="4"><font face="Verdana,Arial" size="-1">Subtotal</font></td>
    <td align="right"><font face="Verdana,Arial" size="-1"><% = formatcurrency(cSubTotal) %></font></td>
  </tr>
<%
  cShipping = session("shipbasecharge") + _
   (nNumItems * session("shipitemcharge"))
%>
  <tr bgcolor="#c5c5c5">
    <td align="center" colspan="4"><font face="Verdana,Arial" size="-1">Shipping &amp;
    Handling</font></td>
    <td align="right"><font face="Verdana,Arial" size="-1"><% = formatcurrency(cShipping) %></font></td>
  </tr>
<% cTotal = cSubTotal + cShipping %>
  <tr bgcolor="#66ff00">
    <td align="center" colspan="4"><font face="Verdana,Arial" size="-1">Grand Total</font></td>
    <td align="right"><font face="Verdana,Arial" size="-1"><% = formatcurrency(cTotal) %></font></td>
  </tr>
</table>
<font face="Verdana,Arial" size="+1">

<dl>
  <dd align="center"><br>
    Thank you for your order!</font></dd>
<% else %>
  <p>The following error(s) occurred while processing the information you provided:<br>
  <br>
  <font face="Courier New" color="#000000"><% = sErrorString %> </font><br>
  <br>
  Please press your browser's BACK button and correct this information, then resubmit your
  order. <br>
<%end if
  if session("salecomplete") = true then
    redim sItemNums(0)
    redim nItemQtys(0)
    sItemNums(0) = ""
    nItemQtys(0) = 0
    session("CartItemNumArray") = sItemNums
    session("CartItemQtyArray") = nItemQtys
    session("salecomplete") = false
  end if
%><!--#INCLUDE FILE="footer.inc"-->  </p>
  </font>
</dl>
</body>
</html>
 

Future Improvement
    1. We can add function to Shopping Cart, user can delete books he has choosed.
    2. Add a login in procedure for user to enter his account, modify his address information.